package com.jsb.service;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;

import javax.annotation.Resource;

import org.apache.log4j.Logger;
import org.springframework.core.task.TaskExecutor;
import org.springframework.stereotype.Service;

import com.jsb.common.utils.DateUtils;
import com.jsb.common.utils.JsonUtil;
import com.jsb.common.utils.StringUtils;
import com.jsb.dto.UserDealRecordDetail;
import com.jsb.mapper.ExUserDealRecordMapper;
import com.jsb.mapper.UserMapper;
import com.jsb.mapper.WithdrawMapper;
import com.jsb.model.User;
import com.jsb.model.UserWx;
import com.jsb.model.Withdraw;
import com.jsb.model.WithdrawExample;
import com.jsb.wx.po.WxEnterpriseRes;
import com.jsb.wx.util.PayCommonUtil;

@Service
public class WithdrawService{
	
	private static final Logger logger = Logger.getLogger(WithdrawService.class);
	
	String timeMillis = String.valueOf(System.currentTimeMillis() / 1000);
	String randomString = PayCommonUtil.getRandomString(32);
	
	@Resource
	private WithdrawMapper withdrawMapper;
	
	@Resource
	private UserMapper userMapper;
	
	@Resource
	private TaskExecutor taskExecutor;// 线程池 
	
	@Resource
	private ExUserDealRecordMapper exUserDealRecordMapper;
	@Resource
	private UserWxService userWxService;
	@Resource
	private SmsSendService smsSendService;
	@Resource
	private UserService userService;
	
	public void addWithdraw(Withdraw withdraw) {
		withdrawMapper.insertSelective(withdraw);
	}
	
	public void delWithdrawByUuid(String uuid) {
		withdrawMapper.deleteByPrimaryKey(uuid);
	}
	
	public void updateWithdraw(Withdraw withdraw) {
		withdrawMapper.updateByPrimaryKeySelective(withdraw);
	}
	
	public void updateWithdrawByExample(Withdraw withdraw,WithdrawExample withdrawExample){
	    withdrawMapper.updateByExampleSelective(withdraw,withdrawExample);
	}
	
	public Withdraw getWithdrawByUuid(String uuid) {
		return withdrawMapper.selectByPrimaryKey(uuid);
	}
	
	public List<Withdraw> getPageWithdraw(WithdrawExample withdrawExample) {
		return withdrawMapper.selectPage(withdrawExample);
	}
	
	public int countWithdraw(WithdrawExample withdrawExample) {
		return withdrawMapper.countByExample(withdrawExample);
	}
	
	public List<Withdraw> selectByExample(WithdrawExample example){
	    return withdrawMapper.selectByExample(example);
	}

	@SuppressWarnings("unchecked")
	public WxEnterpriseRes updatePayEnterprise(Withdraw withdraw1) {
		WxEnterpriseRes res = new WxEnterpriseRes();
		String sn = withdraw1.getUuid();
		Withdraw withdrawByUuid = withdrawMapper.selectByPrimaryKey(sn);
		double amount = withdrawByUuid.getMoney();
		String openid = withdrawByUuid.getOpenid();
		String userid = withdrawByUuid.getPhoneNum();    //userid
		String phone = userService.getUserByPhoneNumber(userid).getPhone();  //phhone
		try {
			BigDecimal totalAmount = new BigDecimal(amount);
			SortedMap<String, Object> parameterMap = new TreeMap<String, Object>();
			parameterMap.put("mch_appid", PayCommonUtil.APPID);
			parameterMap.put("mchid", PayCommonUtil.MCH_ID);
			parameterMap.put("nonce_str", randomString);
			parameterMap.put("partner_trade_no", sn);
			parameterMap.put("openid", openid);
			BigDecimal total = totalAmount.multiply(new BigDecimal(100));
			java.text.DecimalFormat df = new java.text.DecimalFormat("0");
			parameterMap.put("amount", df.format(total));
			parameterMap.put("check_name", "FORCE_CHECK");
			parameterMap.put("re_user_name", withdrawByUuid.getName());
			parameterMap.put("desc", "解税宝微信提现");
			parameterMap.put("spbill_create_ip","60.205.84.1");
			
			String sign = PayCommonUtil.createSign("UTF-8", parameterMap);
			parameterMap.put("sign", sign);
			
			String requestXML = PayCommonUtil.getRequestXml(parameterMap);
			logger.info("微信企业支付请求报文：" + requestXML);
			String result = PayCommonUtil.httpsRequestEnterprise(PayCommonUtil.ENTERPRISE_PAY_URL, requestXML);
			logger.info("企业支付返回报文："+result);
			Map<String,String> map = PayCommonUtil.doXMLParse(result);
			String return_code = map.get("return_code");
			String result_code = map.get("result_code");
			String partner_trade_no = map.get("partner_trade_no");
			String payment_no = map.get("payment_no");
			String payment_time = map.get("payment_time");
			
			if (return_code.equalsIgnoreCase(PayCommonUtil.SUCCESS)) {
				if (result_code.equalsIgnoreCase(PayCommonUtil.SUCCESS)) {  
					//修改提现表状态
					Withdraw withdraw = new Withdraw();
					withdraw.setUuid(partner_trade_no);
					withdraw.setWxid(payment_no);
					withdraw.setSucDate(DateUtils.parseDate(payment_time));
					withdraw.setStatus(PayCommonUtil.PAYSUCCESS_STATUS);
					withdrawMapper.updateByPrimaryKeySelective(withdraw);
					res.setCode(PayCommonUtil.SUCCESS_CODE);
					res.setDes("提现成功");
					UserWx userWxByUserId = userWxService.getUserWxByUserId(userid);
					if(null == userWxByUserId){
						try {
							UserWx userWx = new UserWx();
							userWx.setUserId(userid);
							userWx.setOpenId(openid);
							userWx.setCreateTime(new Date());
							userWxService.addUserWx(userWx);
							logger.warn("内部后台绑定用户微信："+JsonUtil.toJson(userWx));
						} catch (Exception e) {
							e.printStackTrace();
							logger.error("内部后台绑定用户微信出现错误：openid:"+openid+",:"+e.toString());
							return res;
						}
					}
					return res;
				}else{
					String err_code = map.get("err_code");
					String err_code_des = map.get("err_code_des");
					Withdraw withdraw = new Withdraw();
					withdraw.setUuid(sn);
					withdraw.setErrorCode(err_code);
					withdraw.setReason(err_code_des);
					withdrawMapper.updateByPrimaryKeySelective(withdraw);  //保存微信返回错误信息
					logger.warn("保存微信返回错误信息："+JsonUtil.toJson(withdraw));
					//出现错误退回余额
					updateRefund(amount, sn, userid);
					logger.warn("调用微信企业支付：err_code"+err_code+",err_code_des"+err_code_des);
					if(err_code.equalsIgnoreCase("NAME_MISMATCH")){
						try {
							Withdraw withdraw2 = new Withdraw();
							withdraw2.setUuid(sn);
							withdraw2.setStatus(PayCommonUtil.PAY_ERRORNAME_CODE);
							withdrawMapper.updateByPrimaryKeySelective(withdraw2);
							smsSendService.sendSms("8a216da8592b16a1015938d4129f03f0", "156463", phone, null);
						} catch (Exception e) {
							e.printStackTrace();
							logger.error("后台提现失败，发送短信出错："+e.toString());
						}
					}
					res.setCode(PayCommonUtil.FAIL_CODE);
					res.setDes("提现失败，"+err_code_des);
					return res;
				}
			}else {
				Withdraw withdraw = new Withdraw();
				withdraw.setUuid(partner_trade_no);
				withdraw.setStatus(PayCommonUtil.PENDING_QUERY_CODE);
				withdraw.setReason("网络错误，待查询");
				withdrawMapper.updateByPrimaryKeySelective(withdraw);  //记录网络错误后的待查询状态
				//TODO  可能网络出现错误，查询支付结果    线程池中查询支付结果
				this.taskExecutor.execute(new EnterpriseQueryTask(partner_trade_no));  
				res.setCode(PayCommonUtil.FAIL_CODE);
				res.setDes("系统繁忙");
				logger.error("调用微信企业付款通信异常");
				return res;
			}
		}  catch (Exception e) {
			e.printStackTrace();
			//出现错误退回余额      修改为只在微信返回错误的时候退钱，此时状态还是初始状态，后台还可以审核
//			refund(amount, sn, phoneNum);
			res.setCode(PayCommonUtil.FAIL_CODE);
			res.setDes("系统繁忙");
			logger.error("调用微信企业付款通信异常");
			return res;
		}
		
	}
	/**
	 * 提现失败退回余额
	 * @param balance   提现钱余额
	 * @param sn        订单号
	 * @param phoneNumber   手机号
	 */
	private void updateRefund(Double amount, String sn, String phoneNumber) {
		User userByPhoneNumber = userService.getUserByPhoneNumber(phoneNumber);
		Double balance2 = userByPhoneNumber.getBalance();
		User user1 = new User();
		user1.setPhoneNumber(phoneNumber);
		user1.setBalance(balance2+amount);
		Withdraw withdraw1 = new Withdraw();
		withdraw1.setUuid(sn);
		withdraw1.setStatus(PayCommonUtil.ALREADY_REFUND_CODE);
		withdrawMapper.updateByPrimaryKeySelective(withdraw1);//记录退回操作
		logger.warn("记录退回操作："+JsonUtil.toJson(withdraw1));
		userMapper.updateByPrimaryKeySelective(user1);//退回余额
		logger.warn("提现失败退回余额："+JsonUtil.toJson(user1));
	}
	
	/**
	 * 企业支付订单查询
	 * @param wxEnterpriseReq
	 * @param request
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public WxEnterpriseRes enterpriseOrder(String partner_trade_no) {
		WxEnterpriseRes res = new WxEnterpriseRes();
		if(StringUtils.isEmpty(partner_trade_no)){
			res.setCode(PayCommonUtil.FAIL_CODE);
			res.setDes("商户订单号不能为空");
			logger.info("企业支付订单查询时订单号为空 partner_trade_no"+partner_trade_no);
			return res;
		}
		SortedMap<String, Object> parameterMap = new TreeMap<String, Object>();
		parameterMap.put("nonce_str", randomString);
		parameterMap.put("partner_trade_no", partner_trade_no);
		parameterMap.put("mch_id", PayCommonUtil.MCH_ID);
		parameterMap.put("appid", PayCommonUtil.APPID);
		
		String sign = PayCommonUtil.createSign("UTF-8", parameterMap);
		parameterMap.put("sign", sign);
		
		String requestXML = PayCommonUtil.getRequestXml(parameterMap);
		try {
			String result = PayCommonUtil.httpsRequestEnterprise(PayCommonUtil.ENTERPRISE_ORDER_URL, requestXML);
			logger.info("企业付款查询订单返回报文："+result);
			Map<String,String> map = PayCommonUtil.doXMLParse(result);
			String return_code = map.get("return_code");
			String result_code = map.get("result_code");
//			String mch_id = map.get("mch_id");
			//调用企业付款API时，微信系统内部产生的单号
			String detail_id = map.get("detail_id");
			String status = map.get("status");
			String reason = map.get("reason");
//			String openid = map.get("openid");   //转账的openid
//			String transfer_name = map.get("transfer_name");   //收款用户姓名
//			String payment_amount = map.get("payment_amount");  //付款金额单位分）
//			String transfer_time = map.get("transfer_time");    //发起转账的时间
//			String desc = map.get("desc");                      //付款时候的描述
			if (return_code.equalsIgnoreCase(PayCommonUtil.SUCCESS)) {
				if (result_code.equalsIgnoreCase(PayCommonUtil.SUCCESS)) { 
					if(status.equalsIgnoreCase(PayCommonUtil.SUCCESS)){
						Withdraw withdraw = new Withdraw();
						withdraw.setUuid(partner_trade_no);
						withdraw.setWxid(detail_id);
						withdraw.setStatus(PayCommonUtil.PAYSUCCESS_STATUS);
						withdrawMapper.updateByPrimaryKeySelective(withdraw);
						
					}else{    //FAILED:转账失败   PROCESSING:处理中
						logger.info("调用微信企业支付查询订单接口：status"+status+",reason"+reason);
//						Withdraw withdraw = new Withdraw();
//						withdraw.setUuid(partner_trade_no);
//						withdraw.setWxid(detail_id);
////						withdraw.setStatus(PayCommonUtil.PAYSUCCESS_STATUS);
//						withdraw.setErrorCode(status);
//						withdraw.setReason(reason);
//						withdrawService.updateWithdraw(withdraw);
					}
				}else{
					String err_code = map.get("err_code");
					String err_code_des = map.get("err_code_des");
					logger.info("调用微信企业支付查询订单接口：err_code"+err_code+",err_code_des"+err_code_des);
				}
			}else{
				logger.error("调用微信企业付款查询订单接口通信异常");
			}
		} catch (Exception e) {
			logger.error(e);
			res.setCode(PayCommonUtil.FAIL_CODE);
			res.setDes("调用微信企业付款查询订单接口异常");
		}
		return res;
	}
	
	class EnterpriseQueryTask implements Runnable{
		String partner_trade_no;
		int n;
		public EnterpriseQueryTask(String partner_trade_no){
			this.partner_trade_no = partner_trade_no;
		}
		@Override
		public void run() {
			if(n>=3){
				enterpriseOrder(partner_trade_no);
				n++;
			}
		}
		
	}
	
	public List<UserDealRecordDetail> redPacketDetail(Map<String, Object> map){
		return exUserDealRecordMapper.redPacketDetail(map);
	}
}
